package com.glodon.wps.util;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JSON工具类
 * @author wushuai
 * @date 2019/5/20 9:28
 */
public class JSONUtil {
    private static final Logger logger = LoggerFactory.getLogger(JSONUtil.class);

    private final static ObjectMapper objectMapper = new ObjectMapper();

    public static ObjectMapper getInstance() {
        return objectMapper;
    }

    private JSONUtil() {

    }

    /**
     * javaBean、列表数组转换为json字符串
     */
    public static String beanToJson(Object obj) {
        if (obj != null){
            try {
                return objectMapper.writeValueAsString(obj);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }

    /**
     * javaBean、列表数组转换为json字符串,忽略空值
     */
    public static String beanToJsonIgnoreNull(Object obj) {
        if (obj != null){
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            try {
                return mapper.writeValueAsString(obj);
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }

    /**
     * json 转JavaBean
     */
    public static <T> T jsonToBean(String jsonString, Class<T> clazz) {
        if (jsonString != null){
            objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
            try {
                return objectMapper.readValue(jsonString, clazz);
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }
    public static <T> T jsonToBeanIgnoreUndefined(String jsonString, Class<T> clazz) {
        if (jsonString != null){
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
            try {
                T t = objectMapper.readValue(jsonString, clazz);
                return t;
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }
    /**
     * json字符串转换为map
     */
    public static <T> Map<String, Object> jsonToMap(String jsonString) {
        if (jsonString != null){
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            try {
                return mapper.readValue(jsonString, Map.class);
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * json字符串转换为map
     */
    public static <T> Map<String, T> jsonToMap(String jsonString, Class<T> clazz) {
        if (jsonString != null){
            try {
                Map<String, Map<String, Object>> map = (Map<String, Map<String, Object>>) objectMapper.readValue(jsonString, new TypeReference<Map<String, T>>(){});
                Map<String, T> result = new HashMap<String, T>();
                for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {
                    result.put(entry.getKey(), mapToBean(entry.getValue(), clazz));
                }
                return result;
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }

    /**
     * 深度转换json成map
     *
     * @param json
     * @return
     */
    public static Map<String, Object> jsonToMapDeeply(String json) {
        return jsonToMapRecursion(json, objectMapper);
    }

    /**
     * 把json解析成list，如果list内部的元素存在jsonString，继续解析
     *
     * @param json
     * @param mapper 解析工具
     * @return
     * @throws Exception
     */
    private static List<Object> jsonToListRecursion(String json, ObjectMapper mapper) {
        if (json == null) {
            return null;
        }

        try {
            List<Object> list = mapper.readValue(json, List.class);

            for (Object obj : list) {
                if (obj instanceof String) {
                    String str = (String) obj;
                    if (str.startsWith("[")) {
                        obj = jsonToListRecursion(str, mapper);
                    } else if (obj.toString().startsWith("{")) {
                        obj = jsonToMapRecursion(str, mapper);
                    }
                }
            }
            return list;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 把json解析成map，如果map内部的value存在jsonString，继续解析
     *
     * @param json
     * @param mapper
     * @return
     * @throws Exception
     */
    private static Map<String, Object> jsonToMapRecursion(String json, ObjectMapper mapper) {
        if (json == null) {
            return null;
        }

        try {
            Map<String, Object> map = mapper.readValue(json, Map.class);

            for (Map.Entry<String, Object> entry : map.entrySet()) {
                Object obj = entry.getValue();
                if (obj instanceof String) {
                    String str = ((String) obj);

                    if (str.startsWith("[")) {
                        List<?> list = jsonToListRecursion(str, mapper);
                        map.put(entry.getKey(), list);
                    } else if (str.startsWith("{")) {
                        Map<String, Object> mapRecursion = jsonToMapRecursion(str, mapper);
                        map.put(entry.getKey(), mapRecursion);
                    }
                }
            }

            return map;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 与javaBean json数组字符串转换为列表
     */
    public static <T> List<T> jsonToList(String jsonArrayStr, Class<T> clazz) {
        if (jsonArrayStr != null){
            JavaType javaType = getCollectionType(ArrayList.class, clazz);
            try {
                return objectMapper.readValue(jsonArrayStr, javaType);
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }


    /**
     * 获取泛型的Collection Type
     *
     * @param collectionClass 泛型的Collection
     * @param elementClasses  元素类
     * @return JavaType Java类型
     * @since 1.0
     */
    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }


    /**
     * map  转JavaBean
     */
    public static <T> T mapToBean(Map map, Class<T> clazz) {
        return objectMapper.convertValue(map, clazz);
    }

    /**
     * map 转json
     *
     * @param map
     * @return
     */
    public static String mapToJson(Map map) {
        try {
            return objectMapper.writeValueAsString(map);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return "";
    }

    /**
     * map  转JavaBean
     */
    public static <T> T objToBean(Object obj, Class<T> clazz) {
        return objectMapper.convertValue(obj, clazz);
    }

}
